package com.ww.demo.common;

import com.ww.demo.core.annotation.RimsLoggerFactory;
import com.ww.demo.core.entity.response.ErrorResult;
import com.ww.demo.core.exception.BaseException;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.eclipse.jetty.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.BindException;

/**
 * @author liuqingwang
 * @date 2021/10/25 23:41
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler({Exception.class})
    @ResponseBody
    public ErrorResult handlerException(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Exception e) {
        ErrorResult errorResult = new ErrorResult();
        int code = getErrorCode(e);
        response.setStatus(code);
        errorResult.setCode(code);
        errorResult.setExceptionType(e.getClass());
        errorResult.setRequestUrl(request.getRequestURL().toString());
        errorResult.setMessage(e.getMessage());
        errorResult.setStackTrace(ExceptionUtils.getStackTrace(e));
        logError(errorResult);
        return errorResult;
    }

    private int getErrorCode(Exception e) {
        if (e instanceof BindException
                || e instanceof HttpMessageNotReadableException
                || e instanceof MethodArgumentNotValidException
                || e instanceof MissingServletRequestParameterException
                || e instanceof MissingServletRequestPartException
                || e instanceof HttpRequestMethodNotSupportedException
                || e instanceof javax.validation.ValidationException) {
            return HttpStatus.BAD_REQUEST_400;
        } else if (e instanceof NoHandlerFoundException) {
            return HttpStatus.NOT_FOUND_404;
        } else if (e instanceof HttpMediaTypeNotSupportedException) {
            return HttpStatus.UNSUPPORTED_MEDIA_TYPE_415;
        } else if (e instanceof BaseException) {
            return ((BaseException) e).getErrorCode();
        } else {
            return HttpStatus.INTERNAL_SERVER_ERROR_500;
        }
    }

    private void logError(ErrorResult er) {
        if (er.getCode() == HttpStatus.INTERNAL_SERVER_ERROR_500) {
            RimsLoggerFactory.getBackendLog()
                    .error("ThreadId:" + Thread.currentThread().getId() + "&&RequsetedUrl:"
                            + er.getRequestUrl() + "&&Exception:" + er.getExceptionType()
                            + "&&ExceptionMessage:" + er.getMessage() + "&&StackTrace:"
                            + er.getStackTrace());
        }
    }
}
